﻿using ClosedXML.Excel;
using Microsoft.Extensions.Configuration;
using Serilog;
using Spectre.Console;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using WorkTool.Helpers;

namespace WorkTool
{
    public class CherryPick : ITools
    {
        public void ToolsMethod(IConfigurationRoot config)
        {
            var options = new List<(int Index, string Description)>{
                new (1, "是"),
                new (0, "否")
            };
            var isContinue = false;
            while (!isContinue)
            {
                ToolHelper.ConsoleClear();
                var cherryPickSettingsList = SettingsHelper._cherryPickSettings;
                if (cherryPickSettingsList == null || cherryPickSettingsList.Count == 0)
                {
                    AnsiConsole.MarkupLine("[yellow]--------------------没有可操作的数据--------------------[/]");
                    isContinue = true;
                    continue;
                }
                else if (cherryPickSettingsList.Count == 1)
                    isContinue = true;
                else
                {
                    var projects = SettingsHelper._cherryPickSettings.Select(x => x.ProjectName).ToList();
                    projects.Insert(0, "全部");
                    projects.Add("返回上一级");
                    var projectName = AnsiConsole.Prompt(
                        new SelectionPrompt<string>()
                            .Title($"[green1]请选择项目：[/]")
                            .PageSize(10)
                            .UseConverter(option => $"[yellow]【{option}】[/]")
                            .AddChoices(projects));
                    if (projectName.Equals("返回上一级"))
                        return;
                    if (projectName.Equals("全部"))
                        cherryPickSettingsList = SettingsHelper._cherryPickSettings;
                    else
                    {
                        cherryPickSettingsList = SettingsHelper._cherryPickSettings.Where(x => x.ProjectName.Equals(projectName)).ToList();
                    }
                }
                var pathList = new List<string>();
                foreach (var cherryPickSettings in cherryPickSettingsList)
                {
                    AnsiConsole.MarkupLine($"[aqua]--------------------【{cherryPickSettings.ProjectName}】--------------------[/]");
                    if (string.IsNullOrWhiteSpace(cherryPickSettings.ProjectPath))
                    {
                        cherryPickSettings.ProjectPath = AnsiConsole.Ask<string>("[bold][green1]请输入项目路径：[/] [/]");
                    }
                    if (string.IsNullOrWhiteSpace(cherryPickSettings.Author))
                    {
                        cherryPickSettings.Author = AnsiConsole.Ask<string>("[bold][green1]请输入要获取的提交人名称或邮箱：[/] [/]");
                    }
                    var branches = new Dictionary<string, List<GitCommitRecord>> { };
                    var isBranches = false;
                    if (cherryPickSettings.Branches.Count > 0)
                    {
                        var selection = AnsiConsole.Prompt(
                            new SelectionPrompt<(int Index, string Description)>()
                                .Title($"[green1]是否继续输入要获取的分支名称？[/]\n[aqua]已获取配置文件的分支信息：\n{string.Join("\n", cherryPickSettings.Branches)}[/]")
                                .PageSize(10)
                                .UseConverter(option => $"[yellow]【{option.Description}】[/]")
                                .AddChoices(options));
                        switch (selection.Index)
                        {
                            case 0:
                                isBranches = false;
                                break;

                            case 1:
                                isBranches = true;
                                break;

                            default:
                                break;
                        }
                    }
                    if (isBranches)
                    {
                        AnsiConsole.MarkupLine("[bold][green1]请输入要获取的分支名称（至少输入一个分支，为空则结束）：[/] [/]");
                        while (true)
                        {
                            var branchReadLine = Console.ReadLine();
                            if (string.IsNullOrWhiteSpace(branchReadLine))
                                break;
                            cherryPickSettings.Branches.Add(branchReadLine.Trim());
                        }
                    }
                    cherryPickSettings.Branches = cherryPickSettings.Branches.Distinct().ToList();
                    AnsiConsole.MarkupLine("");
                    AnsiConsole.MarkupLine($"[bold][aqua]项目路径：[green1]{cherryPickSettings.ProjectPath}[/][/][/]");
                    AnsiConsole.MarkupLine($"[bold][aqua]提交人名称或邮箱：[green1]{cherryPickSettings.Author}[/][/][/]");
                    AnsiConsole.MarkupLine($"[bold][aqua]分支信息：[green1]{string.Join("\n\t  ", cherryPickSettings.Branches)}[/][/][/]");

                    AnsiConsole.Status().Start("数据加载中...", ctx =>
                    {
                        var (IsSuccess, Message) = GitHelper.ExecuteGitCommand("fetch", cherryPickSettings.ProjectPath);
                        if (!string.IsNullOrWhiteSpace(Message))
                            Log.Error($"[git fetch]{Message}");
                        using var workbook = new XLWorkbook();
                        var sheetIndex = 1;
                        foreach (var branch in cherryPickSettings.Branches)
                        {
                            ctx.Status($"正在获取分支【{branch}】的提交信息...");
                            ctx.Spinner(Spinner.Known.Star);
                            ctx.SpinnerStyle(Style.Parse("green"));
                            Thread.Sleep(1000);
                            var (Data, ErrorMessage) = GitHelper.GetGitCommit(branch, cherryPickSettings.Author, cherryPickSettings.ProjectPath);
                            if (!string.IsNullOrWhiteSpace(ErrorMessage))
                            {
                                AnsiConsole.MarkupLine($"[red]获取分支【{branch}】的提交信息失败\n\t错误信息：\n\t{ErrorMessage}[/]");
                                continue;
                            }
                            var branchList = Data;

                            ctx.Status($"正在处理分支【{branch}】的数据...");
                            ctx.Spinner(Spinner.Known.Star);
                            ctx.SpinnerStyle(Style.Parse("green"));
                            Thread.Sleep(1000);
                            var worksheetName = branch.Replace("/", "_");
                            worksheetName = worksheetName.Length > 31 ? worksheetName[..31] : worksheetName;
                            var worksheet = workbook.Worksheets.Add(worksheetName, sheetIndex);
                            var columnIndex = 0;
                            var properties = typeof(GitCommitRecord).GetProperties();
                            for (int i = 0; i < properties.Length; i++)
                            {
                                var prop = properties[i];
                                var descriptionAttr = prop.GetCustomAttribute<DescriptionAttribute>();
                                if (descriptionAttr != null)
                                {
                                    worksheet.Cell(1, i + 1).Value = descriptionAttr.Description;
                                    worksheet.Cell(1, i + 1).Style.Font.Bold = true;
                                    worksheet.Cell(1, i + 1).Style.Font.FontColor = XLColor.White;
                                    worksheet.Cell(1, i + 1).Style.Fill.BackgroundColor = XLColor.FromArgb(0, 112, 192);
                                    columnIndex++;
                                }
                            }
                            worksheet.Cell(2, 1).InsertData(branchList);
                            worksheet.Columns().AdjustToContents();
                            var range = worksheet.Range(1, 1, branchList.Count + 1, columnIndex);
                            range.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
                            range.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
                            sheetIndex++;
                            branches.Add(branch, branchList);
                        }

                        ctx.Status("生成Excel文件中...");
                        ctx.Spinner(Spinner.Known.Star);
                        ctx.SpinnerStyle(Style.Parse("green"));
                        Thread.Sleep(1000);
                        if (sheetIndex > 1)
                        {
                            cherryPickSettings.Branches = [.. branches.Keys];
                            var allWorksheetName = string.IsNullOrEmpty(cherryPickSettings.ProjectName) ? "cherry-pick" : cherryPickSettings.ProjectName.Replace("/", "_") + "_cherry-pick";
                            allWorksheetName = allWorksheetName.Length > 31 ? allWorksheetName[..31] : allWorksheetName;
                            var allWorksheet = workbook.Worksheets.Add("cherry-pick", 0);
                            allWorksheet.Cell(1, 1).Value = "git cherry-pick";
                            allWorksheet.Cell(1, 2).Value = "简短提交id";
                            allWorksheet.Cell(1, 3).Value = "完整提交id";
                            allWorksheet.Cell(1, 4).Value = "提交信息";
                            var index = 5;
                            foreach (var branch in cherryPickSettings.Branches)
                            {
                                allWorksheet.Cell(1, index).Value = branch;
                                index++;
                            }
                            for (int i = 1; i < index; i++)
                            {
                                allWorksheet.Cell(1, i).Style.Font.Bold = true;
                                allWorksheet.Cell(1, i).Style.Font.FontColor = XLColor.White;
                                allWorksheet.Cell(1, i).Style.Fill.BackgroundColor = XLColor.FromArgb(0, 112, 192);
                            }
                            var rowIndex = 2;
                            foreach (var item in branches[cherryPickSettings.Branches[0]])
                            {
                                var shortCommitIdCell = allWorksheet.Cell(rowIndex, 2);
                                shortCommitIdCell.Value = item.ShortCommitId;
                                var commitIdCell = allWorksheet.Cell(rowIndex, 3);
                                commitIdCell.Value = item.CommitId;
                                var messageCell = allWorksheet.Cell(rowIndex, 4);
                                messageCell.Value = item.Message;
                                var masterCell = allWorksheet.Cell(rowIndex, 5);
                                masterCell.Value = "Y";
                                masterCell.Style.Font.FontColor = XLColor.White;
                                masterCell.Style.Fill.BackgroundColor = XLColor.Green;
                                var columnIndex = 6;
                                var isGit = true;
                                foreach (var prop in branches.Keys.Where(x => !x.Equals(cherryPickSettings.Branches[0])))
                                {
                                    var isBool = branches[prop].Exists(x => x.CommitId.Equals(item.CommitId));
                                    if (!isBool)
                                    {
                                        if (branches[prop].Exists(x => x.Message.Equals(item.Message)))
                                        {
                                            isBool = true;
                                        }
                                        else
                                        {
                                            isBool = branches[prop].Any(x => x.Message.Contains(item.ShortCommitId));
                                        }
                                    }
                                    var cell = allWorksheet.Cell(rowIndex, columnIndex);
                                    if (isBool)
                                    {
                                        cell.Value = "Y";
                                        cell.Style.Font.FontColor = XLColor.White;
                                        cell.Style.Fill.BackgroundColor = XLColor.Green;
                                    }
                                    else
                                    {
                                        isGit = false;
                                        cell.Value = "N";
                                        cell.Style.Fill.BackgroundColor = XLColor.FromArgb(255, 255, 0);
                                    }
                                    columnIndex++;
                                }
                                if (!isGit)
                                {
                                    var gitCell = allWorksheet.Cell(rowIndex, 1);
                                    gitCell.Value = isGit ? "" : $"git cherry-pick {item.ShortCommitId}";
                                    allWorksheet.Row(rowIndex).Cells(1, 4).Style.Fill.SetBackgroundColor(XLColor.FromArgb(255, 255, 0));
                                }
                                rowIndex++;
                            }
                            allWorksheet.Columns().AdjustToContents();
                            var allRange = allWorksheet.Range(1, 1, rowIndex - 1, index - 1);
                            allRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
                            allRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
                        }
                        var excelPath = Path.Combine(SettingsHelper._fileSettings.SaveFolder, $"{cherryPickSettings.ProjectName}_GitCommitRecord_{DateTime.Now:yyyyMMdd}{(SettingsHelper._fileSettings.SaveFileNameRandom ? $"_{new Random().Next(10000, 99999)}" : "")}.xlsx");
                        workbook.SaveAs(excelPath);
                        AnsiConsole.MarkupLine($"[green1]文件已保存至\n[/] [bold][aqua]{excelPath}[/][/]");
                        pathList.Add(excelPath);
                    });
                }
                foreach (var path in pathList)
                {
                    Process.Start(new ProcessStartInfo
                    {
                        FileName = path,
                        UseShellExecute = true
                    });
                }
                AnsiConsole.MarkupLine("[grey]按任意键继续...[/]");
                Console.ReadKey();
            }
        }
    }
}